const place = {
  // 城市代码列表
  11: '北京',
  12: '天津',
  13: '河北',
  14: '山西',
  15: '内蒙古',
  21: '辽宁',
  22: '吉林',
  23: '黑龙江',
  31: '上海',
  32: '江苏',
  33: '浙江',
  34: '安徽',
  35: '福建',
  36: '江西',
  37: '山东',
  41: '河南',
  42: '湖北',
  43: '湖南',
  44: '广东',
  45: '广西',
  46: '海南',
  50: '重庆',
  51: '四川',
  52: '贵州',
  53: '云南',
  54: '西藏 ',
  61: '陕西',
  62: '甘肃',
  63: '青海',
  64: '宁夏',
  65: '新疆',
  71: '台湾',
  81: '香港',
  82: '澳门',
  91: '国外'
};

/** 身份证号检查接口 */
interface ICheckIdCard {
  /** 是否有效 */
  isValidate: boolean;

  /** 错误消息 */
  message: string;
}

/**
 * 身份证工具类
 */
export class Identity {
  // 定义一个受保护的_card属性，类型为字符串
  protected _card: string;
  // 构造函数，接收一个card参数，并将其赋值给_card属性
  constructor(card: string) {
    this._card = card;
  }

  /**
   * 校验身份证号码
   */
  get validate() {
    return Identity.checkIdCard(this._card).isValidate;
  }

  /**
   * 获取籍贯
   */
  get nativePlace(): string {
    if (!this.validate) {
      return '';
    }
    return place[parseInt(this._card.substring(0, 2))];
  }

  /**
   * 获取生日
   */
  get birthday() {
    if (!this.validate) {
      return '';
    }
    const year = this._card.substring(6, 10),
      month = this._card.substring(10, 12),
      date = this._card.substring(12, 14);
    return `${year}-${month}-${date}`;
  }

  /**
   * 获取年龄
   */
  get age() {
    if (!this.validate) {
      return -1;
    }
    const birthday = new Date(this.birthday);
    const now = new Date();
    return now.getFullYear() - birthday.getFullYear();
  }

  // 定义一个gender属性，用于获取身份证号码的性别
  get gender() {
    if (!this.validate) {
      return '';
    }
    return +this._card.substring(16, 17) % 2 == 0 ? '女' : '男';
  }

  /**
   * 静态方法，用于校验身份证号码
   * @param idCard 身份证号码
   * @returns
   */
  static checkIdCard(idCard: string): ICheckIdCard {
    let message = '',
      isValidate = true;
    // 1、正则表达式，用于校验身份证号码格式
    const reg =
      /^(([1][1-5])|([2][1-3])|([3][1-7])|([4][1-6])|([5][0-4])|([6][1-5])|([7][1])|([8][1-2])|91)\d{4}(([1][9]\d{2})|([2]\d{3}))(([0][1-9])|([1][0-2]))(([0][1-9])|([1-2][0-9])|([3][0-1]))\d{3}[0-9xX]$/;
    // 如果身份证号码格式不正确，返回错误信息
    if (!reg.test(idCard)) {
      isValidate = false;
      message = '格式不正确，请输入正确的身份证号码';
    }
    // 2、出生年月日校验   前正则限制起始年份为1900;
    const year = idCard.substring(6, 10), //身份证年
      month = idCard.substring(10, 12), //身份证月
      date = idCard.substring(12, 14), //身份证日
      time = Date.parse(month + '-' + date + '-' + year), //身份证日期时间戳date
      now_time = Date.parse(new Date().toString()), //当前时间戳
      dates = new Date(parseInt(year), parseInt(month), 0).getDate(); //身份证当月天数
    if (time > now_time || parseInt(date) > dates) {
      isValidate = false;
      message = '日期校验不正确，请填写正确的“身份证号”！';
    }
    // 3、校验码判断
    var cArr = new Array(7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2); //系数
    var b = new Array('1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'); //校验码对照表
    var id_array = idCard.split('');
    var sum = 0;
    for (var k = 0; k < 17; k++) {
      sum += parseInt(id_array[k]) * cArr[k];
    }
    if (id_array[17].toUpperCase() != b[sum % 11].toUpperCase()) {
      isValidate = false;
      message = '校验码不正确，请填写正确的“身份证号”！';
    }
    return {
      isValidate,
      message
    };
  }
}
